package top.healthylife.basics.utils.utils;

import java.beans.Introspector;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

/**
 * 自定义获取属性名方法
 *
 * @author maoxiaomeng
 */
public class Get {

    static Map<TypeFunction<?,?>, String> map = new HashMap<>();

    /**
     * 获取对象属性名,使用方法为    Get.name(R::getCode)     =  "code"
     * 这样的编写方式可以不用每次都写固定参数名的值
     *
     * @param name 操作类型
     * @param <T>  入参对象Class
     * @param <R>  返回的结果字段串
     * @return 属性名
     */
    public static <T, R> String name(TypeFunction<T, R> name) {
        if (map.containsKey(name)) {
            return map.get(name);
        }
        String lambdaColumnName = TypeFunction.getLambdaColumnName(name);
        map.put(name, lambdaColumnName);
        return lambdaColumnName;
    }

    /**
     * 自定义序列化获取属性名
     *
     * @author My_gj
     */
    @FunctionalInterface
    public interface TypeFunction<T, R> extends Serializable, Function<T, R> {

        /**
         * 获取列名称
         *
         * @param lambda
         * @return String
         */
        static String getLambdaColumnName(Serializable lambda) {
            try {
                Method method = lambda.getClass().getDeclaredMethod("writeReplace");
                method.setAccessible(Boolean.TRUE);
                SerializedLambda serializedLambda = (SerializedLambda) method.invoke(lambda);
                String getter = serializedLambda.getImplMethodName();
                return Introspector.decapitalize(getter.replace("get", ""));
            } catch (ReflectiveOperationException e) {
                throw new RuntimeException(e);
            }
        }
    }

}
